package edu.bupt.producerconsumer;

import java.util.LinkedList;
import java.util.Queue;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class Controller3 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		Controller3 resource = new Controller3();
		new Thread(new Producer(resource)).start();
		new Thread(new Producer(resource)).start();
		new Thread(new Consumer(resource)).start();
		new Thread(new Producer(resource)).start();
		new Thread(new Consumer(resource)).start();
	}
	
	private static int number = 0;
	private Queue<Integer> queue = new LinkedList<Integer>();
	private Lock lock = new ReentrantLock();
	private Condition notfull = lock.newCondition();
	private Condition notEmpty = lock.newCondition();
	
	public void increase(){
		lock.lock();
		try {
			while(queue.size()==10){
					System.out.println("queue is full!");
					try {
						notfull.await();
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
			}
			System.out.println(Thread.currentThread().getName() + "生产： " + number);
			queue.offer(number);
			number++;
			notEmpty.signal();
		}finally{
			lock.unlock();
		}
	}
	
	public void decrease(){
		lock.lock();
		try{
		while(queue.size()==0){
			try {
				System.out.println("queue is Empty!");
				notEmpty.await();
			} catch (Exception e) {
				e.printStackTrace();
			}
		}
		System.out.println(Thread.currentThread().getName() + "消费： " + queue.poll());
		notfull.signal();
	}finally{
		lock.unlock();
	}
	}
	static class Producer implements Runnable{
		
		private Controller3 resource;
		public Producer(Controller3 resource) {
			this.resource = resource;
		}

		@Override
		public void run() {
			for(int i = 0 ; i < 10 ; i++){
				resource.increase();
				try {
					Thread.sleep(500);
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
			
		}
		
	}
	
	static class Consumer implements Runnable{
		
		private Controller3 resource;
		public Consumer(Controller3 resource) {
			this.resource = resource;
		}

		@Override
		public void run() {
			for(int j = 0 ;j < 15;j++){
				resource.decrease();
				try {
					Thread.sleep(1000);
				} catch (Exception e) {
					// TODO: handle exception
				}
			}
		}
		
	}

	
	
}
